package com.sdy.fs.web.controller;

import com.sdy.common.constant.Constants;
import com.sdy.common.model.FileObj;
import com.sdy.common.model.Response;
import com.sdy.common.utils.StringUtil;
import com.sdy.fs.biz.model.MetaFile;
import com.sdy.fs.biz.service.FileService;
import com.sdy.fs.biz.service.MetaFileService;
import com.sdy.mvc.controller.BaseController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.UUID;

@Slf4j
@Controller
@RequestMapping("/file")
public class FileController extends BaseController {
    @Value("${fs.domain}")
    private String fsDomain;
    @Autowired
    private FileService fileService;
    @Autowired
    private com.sdy.mvc.service.FileService fileService2;
    @Autowired
    private MetaFileService metaFileService;
    
    @PostConstruct
    public void init() {
        File file = new File("/opt/temp");
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 文件上传
     */
    @PostMapping("/upload")
    @ResponseBody
    public Response upload(MultipartFile file, String type, Integer auth) throws Exception {
        if (StringUtil.isBlank(type)) {
            type = "common";
        }
        if (!StringUtil.isAlphanumeric(type)) {
            return Response.error("类型字段只能为字母和数字");
        }
        FileObj fo = fileService2.saveFile(file, type);
        String localPath = fo.getPath();
        String fileId = UUID.randomUUID().toString();
        if (auth != null) {
            fo.setPath(fsDomain.concat("/file/get?fileId=").concat(fileId));
        } else {
            fo.setPath(fo.getPath().replace(Constants.UPLOAD_FILE_PATH, fsDomain.concat("/file/origin")));
        }
        Date date = new Date();
        metaFileService.save(new MetaFile()
                .setId(fileId)
                .setType(type)
                .setFileSize(fo.getFileSize())
                .setFileName(fo.getFileName())
                .setUrl(fo.getPath())
                .setLocalPath(localPath)
                .setCreateTime(date)
        );
        fo.setId(fileId);
        fo.setCreateTime(date);
        return Response.success(fo);
    }

    @GetMapping("/get")
    public ResponseEntity<FileSystemResource> get(String fileId) throws UnsupportedEncodingException {
        if (StringUtil.isEmpty(fileId)) {
            return null;
        }
        MetaFile metaFile = metaFileService.getById(fileId);
        if (metaFile == null) {
            return null;
        }
        File file = fileService.getFileByDir(metaFile.getLocalPath());
        if (file == null) {
            return null;
        }
        MediaType contentType;
        HttpHeaders headers = new HttpHeaders();
        if (file.getName().endsWith(".png")) {
            contentType = MediaType.IMAGE_PNG;
        } else if (file.getName().endsWith(".jpg")) {
            contentType = MediaType.IMAGE_JPEG;
        } else if (file.getName().endsWith(".gif")) {
            contentType = MediaType.IMAGE_GIF;
        } else {
            contentType = MediaType.APPLICATION_OCTET_STREAM;
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Content-Disposition", "attachment; filename="
                    + URLEncoder.encode(metaFile.getFileName(), "UTF-8").replace("+", " "));
        }
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        headers.add("Last-Modified", new Date().toString());
        headers.add("ETag", String.valueOf(System.currentTimeMillis()));

        return ResponseEntity.ok().headers(headers)
                .contentLength(file.length())
                .contentType(contentType)
                .body(new FileSystemResource(file));
    }

    @GetMapping("/origin/{type}/{name}")
    public ResponseEntity<FileSystemResource> originFile(@PathVariable("type") String type, @PathVariable("name") String name) {
        if (StringUtil.isEmpty(type)) {
            return null;
        }
        if (StringUtil.isEmpty(name)) {
            return null;
        }
        File file = fileService.getFileByDir(Constants.UPLOAD_FILE_PATH.concat("/").concat(type).concat("/").concat(name));
        if (file == null) {
            return null;
        }
        MediaType contentType;
        HttpHeaders headers = new HttpHeaders();
        if (file.getName().endsWith(".png")) {
            contentType = MediaType.IMAGE_PNG;
        } else if (file.getName().endsWith(".jpg")) {
            contentType = MediaType.IMAGE_JPEG;
        } else if (file.getName().endsWith(".gif")) {
            contentType = MediaType.IMAGE_GIF;
        } else {
            contentType = MediaType.APPLICATION_OCTET_STREAM;
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Content-Disposition", "attachment; filename=" + file.getName());
        }
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        headers.add("Last-Modified", new Date().toString());
        headers.add("ETag", String.valueOf(System.currentTimeMillis()));

        return ResponseEntity.ok().headers(headers)
                .contentLength(file.length())
                .contentType(contentType)
                .body(new FileSystemResource(file));
    }
}
